﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WFNetLib;
using System.IO.Ports;
using System.Diagnostics;

namespace 邻苯浓度测量仪
{
    /// <summary>
    /// 包头
    /// </summary>
    public class ComParketHead
    {
        /// <summary>
        /// 包头大小
        /// </summary>        
        public static Int32 DataLen_SIZE = 2;
        public static Int32 CommandLen_SIZE = 2;
        public static Int32 HEAD_SIZE = 6;
        public UInt16 Command;
        public UInt16 Len = 0;
        public byte[] Data;
        public ComParketHead()
        {
            Data = new byte[HEAD_SIZE];
        }
    }
    public class ComParket
    {
        public ComParketHead Header;
        public byte[] Data;
        public int RxCount;
        public byte[] RxList;
        public UInt16 NeedCommand;
        public static Int32 BUFFER_SIZE = 1024;
        public ComParket(UInt16 com)
        {
            NeedCommand=com;
            Header=new ComParketHead();
            RxCount = 0;
        }
        public ComParket()
        {
            NeedCommand=0xffff;
            Header=new ComParketHead();
            RxCount = 0;
        }
        public static byte[] MakeComParket(UInt16 com, byte b)
        {
            return MakeComParket(com, new byte[] { b });
        }
        public static byte[] MakeComParket(UInt16 com,  byte[] data)
        {
            byte[] txbuffer;
            if(data!=null)
            {
                txbuffer = new byte[ComParketHead.HEAD_SIZE + data.Length + 2];
                txbuffer[0] = 0xAA;
                txbuffer[1] = 0xEE;               
                txbuffer[2] = BytesOP.GetHighByte((UInt16)(data.Length+8));
                txbuffer[3] = BytesOP.GetLowByte((UInt16)(data.Length + 8));
                txbuffer[4] = BytesOP.GetHighByte(com);
                txbuffer[5] = BytesOP.GetLowByte(com);
                for (int i = 0; i < data.Length; i++)
                {
                    txbuffer[i + ComParketHead.HEAD_SIZE] = data[i];
                }
                UInt16 vy = GetVerify_byteSum(txbuffer, ComParketHead.HEAD_SIZE + data.Length);
                txbuffer[ComParketHead.HEAD_SIZE + data.Length] = BytesOP.GetHighByte(vy);
                txbuffer[ComParketHead.HEAD_SIZE + data.Length + 1] = BytesOP.GetLowByte(vy);
            }
            else
            {
                txbuffer = new byte[ComParketHead.HEAD_SIZE + 2];
                txbuffer[0] = 0xAA;
                txbuffer[1] = 0xEE;
                txbuffer[2] = 0x00;
                txbuffer[3] = 0x08;
                txbuffer[4] = BytesOP.GetHighByte(com);
                txbuffer[5] = BytesOP.GetLowByte(com);
                UInt16 vy = GetVerify_byteSum(txbuffer, ComParketHead.HEAD_SIZE);
                txbuffer[ComParketHead.HEAD_SIZE] = BytesOP.GetHighByte(vy);
                txbuffer[ComParketHead.HEAD_SIZE + 1] = BytesOP.GetLowByte(vy);
            }            
            return txbuffer;
        }
        public bool DataPacketed(byte rx)
        {
            if(RxCount<ComParketHead.HEAD_SIZE)
            {
                Header.Data[RxCount++]=rx;
                if(RxCount==1)
                {
                    if(Header.Data[0]!=0xbb)
                    {
                        RxCount=0;
                    }
                }
                else if(RxCount==2)
                {
                    if(Header.Data[1]!=0xee)
                    {
                        RxCount=0;
                    }
                }
                else if(RxCount==4)
                {
                    Header.Len=BytesOP.MakeShort(Header.Data[2],Header.Data[3]);
                    Data=new byte[Header.Len];
                }
                else if (RxCount == 6)
                {
                    Header.Command = BytesOP.MakeShort(Header.Data[4], Header.Data[5]);
                    if (Header.Command != NeedCommand)
                    {
                        RxCount = 0;
                    }
                    else
                    {
                        for (int i = 0; i < ComParketHead.HEAD_SIZE; i++)
                        {
                            Data[i] = Header.Data[i];
                        }
                    }
                }
            }
            else
            {
                Data[RxCount++]=rx;
                if(RxCount==Header.Len)
                {
                    UInt16 vy = GetVerify_byteSum(Data, Header.Len-2);
                    UInt16 rxvy = BytesOP.MakeShort(Data[Header.Len - 2], Data[Header.Len - 1]);
                    if (vy==rxvy)
                    {
                        return true;
                    }
                    else
                    {
                        RxCount = 0;
                        return false;
                    }
                }
            }
            return false;
        }
//         public static ComParket CP1616ComProc(ref SerialPort serialPort, byte com, ushort addr, uint b)
//         {
//             ushort b1, b2;
//             b1 = BytesOP.GetHighShort(b);
//             b2 = BytesOP.GetLowShort(b);
//             return CP1616ComProc(ref serialPort, com, addr, new byte[4] { BytesOP.GetHighByte(b1), BytesOP.GetLowByte(b1), BytesOP.GetHighByte(b2), BytesOP.GetLowByte(b2) },5);
//         }
//         public static ComParket CP1616ComProc(ref SerialPort serialPort, byte com, ushort addr, ushort b)
//         {
//             return CP1616ComProc(ref serialPort, com, addr, new byte[2] { BytesOP.GetHighByte(b), BytesOP.GetLowByte(b) },5);
//         }
        public static ComParket ComProc(ref SerialPort serialPort, UInt16 com, byte[] data)
        {
            return ComProc(ref serialPort, com, data, 5);
        }
        public static ComParket ComProc(ref SerialPort serialPort, UInt16 com, byte[] data, int retry)
        {
            ComParket ret = new ComParket((UInt16)(com+1));
            byte[] tx;
            tx = ComParket.MakeComParket(com,  data);            
            while (retry != 0)
            {
                serialPort.Write(tx, 0, tx.Length);
                while (true)
                {
                    try
                    {
                        if (ret.DataPacketed((byte)serialPort.ReadByte()))
                        {
                            return ret;
                        }
                    }
                    catch// (Exception ex)
                    {
                        //Debug.WriteLine("血糖通信失败" + ex.Message);
                        break;
                    }
                }
                retry--;
            }
            return null;
        }
        static public UInt16 GetVerify_byteSum(byte[] pBuff, int count)
        {
            UInt16 sum = 0;
            for (int i = 0; i < count; i++)
                sum = (UInt16)(sum + pBuff[i]);
            return sum;
        }
        public static float ComProc_Byte2Float(byte[] data,int offset)
        {
            byte[] conver = new byte[4];
            for (int i = 0; i < 4; i++)
            {
                conver[i] = data[offset + 3 - i];
            }
            return BitConverter.ToSingle(conver,0);
        }
        public static byte[] ComProc_Float2Byte(float f)
        {
            byte[] ret = new byte[4];
            byte[] s = BitConverter.GetBytes(f);
            for (int i = 0; i < 4; i++)
            {
                ret[i] = s[3 - i];
            }
            return ret;
        }
    }
    public class SumVerify
    {
        static public UInt16 GetVerify_byteSum(byte[] pBuff, int count)
        {
            UInt16 sum = 0;
            for (int i = 0; i < count; i = i * 2)
                sum = (UInt16)(sum + BytesOP.MakeShort(pBuff[i], pBuff[i + 1]));
            return sum;
        }
    }
}
